package com.luming.common.file;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @ProjectName: 下载工具类
 * @Package: com.jeeplus.common.utils
 * @ClassName: DownloadUtil
 * @Author: MC
 * @Description: ${description}
 * @Date: 2019/10/14 0014 15:14
 * @Version: 1.0
 */
public class DownloadUtil {
    protected static final Logger logger = LoggerFactory.getLogger(DownloadUtil.class);
    /**
     * @Method 根据URL路径下载网络资源并保存到指定路径并指定下载后保存文件的名称
     * @Author MC
    url:要下载的网络资源路径
    filePath:资源下载后要保存的路径
    fileName:资源下载后要保存的文件名称
    method:请求网络资源下载时指定请求方式,默认为GET
     * @Return
     * @Date 2019/10/14 0014 15:29
     */
    public static boolean downloadFile(String url, String filePath,String fileName, String method){
        if(StrUtil.isEmpty(url) || StrUtil.isEmpty(filePath) || StrUtil.isEmpty(fileName)){
            return false;
        }

        //创建不同的文件夹目录
        File file=new File(filePath);
        //判断文件夹是否存在
        if (!file.exists())
        {
            //如果文件夹不存在，则创建新的的文件夹
            file.mkdirs();
        }
        FileOutputStream fileOut = null;
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        BufferedOutputStream bos = null;
        BufferedInputStream bis = null;
        try
        {
            // 建立链接
            URL httpUrl=new URL(url);
            conn=(HttpURLConnection) httpUrl.openConnection();
            if(!StrUtil.isEmpty(method)){
                //以Post方式提交表单，默认get方式
                conn.setRequestMethod(method);
            }
            conn.setDoInput(true);
            conn.setDoOutput(true);
            // post方式不能使用缓存
            conn.setUseCaches(true);
            //连接指定的资源
            conn.connect();
            //获取网络输入流
            inputStream=conn.getInputStream();
            bis = new BufferedInputStream(inputStream);
            //判断文件的保存路径后面是否以/结尾
            if (!filePath.endsWith("/")) {
                filePath += "/";
            }
            //写入到文件（注意文件保存路径的后面一定要加上文件的名称）
            fileOut = new FileOutputStream(filePath+fileName);
            bos = new BufferedOutputStream(fileOut);

            byte[] buf = new byte[4096];
            int length = bis.read(buf);
            //保存文件
            while(length != -1)
            {
                bos.write(buf, 0, length);
                length = bis.read(buf);
            }
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }finally {
            try {
                bos.close();
                bis.close();
                conn.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    /**
     * @Method 解压文件，指定路径进行解压，指定解压后的名称和后缀类型
     * @Author MC
    sourcedir:要解压的文件路径
    outputFileName:解压后输出的文件名称
    outputFileSuf:解压后输出的文件后缀名
     * @Return
     * @Date 2019/10/14 0014 15:43
     */
    public static String decompressionFile(String sourcedir,String outputFileName,String outputFileSuf){
        if(StrUtil.isEmpty(sourcedir) || StrUtil.isEmpty(outputFileSuf)){
         return null;
        }

        String ouputfile = "";
        GZIPInputStream gzin = null;
        FileInputStream fin = null;
        FileOutputStream fout = null;
        try {
            //建立gzip压缩文件输入流
            fin = new FileInputStream(sourcedir);
            //建立gzip解压工作流
            gzin = new GZIPInputStream(fin);
            if(StrUtil.isEmpty(outputFileName)){
                //建立解压文件输出流
                ouputfile = sourcedir.substring(0,sourcedir.lastIndexOf('.')) +"."+ outputFileSuf;
            }else{
                ouputfile = sourcedir.substring(0,sourcedir.lastIndexOf(File.separator))+File.separator +outputFileName +"."+ outputFileSuf;
            }
            fout = new FileOutputStream(ouputfile);

            int num;
            byte[] buf=new byte[4096];

            while ((num = gzin.read(buf,0,buf.length)) != -1)
            {
                fout.write(buf,0,num);
            }
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }finally {
            try {
                gzin.close();
                fout.close();
                fin.close();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
        return ouputfile;
    }

    /**
     * @Method 解压文件为json格式，并径读取json文件并转换为对应的实体bean
     * @Author MC
    sourcedir:待解压的文件路径
    calzz:json解析后要映射的Bean
     * @Return
     * @Date 2019/10/14 0014 15:59
     */
    public static <T>T decompression2JsonFile2Bean(String sourcedir,String outputFileName, Class<T> calzz) throws IOException {
        String jsonFilePath = decompressionFile(sourcedir, outputFileName, "json");
        if(!StrUtil.isEmpty(jsonFilePath)){
            File file = new File(jsonFilePath );
            cn.hutool.core.io.file.FileReader fileReader = new FileReader(file);
            String jsonStr = fileReader.readString();
            T bean = JSONUtil.toBean(jsonStr, calzz);
            return bean;
        }
        return null;
    }


    /**
     * 解压文件到指定目录
     *
     * @param zipFile
     * @param descDir
     * @author isea533
     */
    @SuppressWarnings("rawtypes")
    public static void unZipFiles(File zipFile, String descDir) throws IOException {
        File pathFile = new File(descDir);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));
        for (Enumeration entries = zip.entries(); entries.hasMoreElements(); ) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String zipEntryName = entry.getName();
            InputStream in = zip.getInputStream(entry);
            String outPath = (descDir + zipEntryName).replaceAll("\\*", "/");
            ;
            //判断路径是否存在,不存在则创建文件路径
            File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
            if (!file.exists()) {
                file.mkdirs();
            }
            //判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
            if (new File(outPath).isDirectory()) {
                continue;
            }
            //输出文件路径信息
            System.out.println(outPath);

            OutputStream out = new FileOutputStream(outPath);
            byte[] buf1 = new byte[1024];
            int len;
            while ((len = in.read(buf1)) > 0) {
                out.write(buf1, 0, len);
            }
            in.close();
            out.close();
        }
        System.out.println("******************解压完毕********************");
    }


    public static void main(String[] args) throws IOException {

        Properties p = new Properties();
        String hanlpRoot = p.getProperty("root");
        String fileUrl = p.getProperty("dataZipFileURL");


        //String url = "https://codeload.github.com/hankcs/HanLP/zip/refs/heads/1.x";
        DownloadUtil.downloadFile(fileUrl,hanlpRoot ,"data.zip", null);

        DownloadUtil.unZipFiles(new File(hanlpRoot+File.separator+"data.zip"), hanlpRoot+File.separator);
    }


}
